#include <skyroad/archive/bin_iarchive.hpp>

void bin_iarchive::read(unsigned char& c)
{
    if (m_error)
    {
        return;
    }

    c = 0;
    if (m_first+1 <= m_last) 
    {
        c = *m_first++;
    }
}

void bin_iarchive::read(unsigned short& s)
{
    if (m_error)
    {
        return;
    }

    s = 0;
    if (m_first+sizeof(s) <= m_last)
    {
        s = *((unsigned short*)m_first);
        m_first += sizeof(s);
    }
}

void bin_iarchive::read(unsigned long& l)
{
    if (m_error) return;

    l = 0;
    if (m_first+sizeof(l) <= m_last) 
    {
        l = *((unsigned long*)m_first);
        m_first+= sizeof(l);
    }
}

void bin_iarchive::read(unsigned __int64& i64)
{
    if (m_error) return;

    i64 = 0;
    if (m_first+sizeof(i64) <= m_last)
    {
        i64 = *((unsigned __int64*)m_first);
        m_first+= sizeof(i64);
    }
}

void bin_iarchive::read(float& f) 
{
    if (m_error) return;

    if (m_first + sizeof(f) <= m_last) 
    {
        f = *((float*)m_first);
        m_first+= sizeof(f);
    }
}

void bin_iarchive::read(std::string& s) 
{
    if (m_error) return;

    s.clear();
    while (m_first < m_last && *m_first != 0)
    {
        s += *m_first++;
        if (s.size() > 1024)
        {
            m_error = true;
            return;
        }
    }

    if (m_first < m_last ) m_first++;
}

void bin_iarchive::read(std::wstring& s)
{
    if (m_error) return;

    s.clear();
    const wchar_t* it = (const wchar_t*)begin();
    const wchar_t* last = (const wchar_t*)end();
    while (it < last && *it != 0)
    {
        s += *it++;
        if (s.size() > 1024)
        {
            m_error = true;
            return;
        }
    }

    if (it < last ) it++;
    seek((const unsigned char*)it);
}

void bin_iarchive::read(unsigned char* buffer, std::size_t count)
{
    if (m_error) return;

    if (count > 1024) 
    {
        m_error = true;
        return;
    }

    using namespace std;
    const unsigned char* pos = min(m_first+count, m_last);
    std::copy(m_first, pos, buffer);
    m_first = pos;
}

